<?php
require_once 'vendor/autoload.php';

/**
 * 消息推送驱动器组件：APP.JPush
 * 
 * @date	2017年7月19日 下午1:05:53
 * 
 */
class MessagePusherApp_JPush extends CI_Driver implements libraries\common\MessagePusherInterface
{
	const DEBUG_MODE = false;
	
	private $msgTitle  = "哥，有提醒：";
	private $appkey    = "db18362161bf2645f992de85";
	private $msaterSecret = "e9eff13e602683bd29921334";
	private $aliasPre  = "alias_";      // alias   对应用户
	private $tagPre    = "tag_";        // tag     对应地区、驻地、站点、商城等
	private $tagAndPre = "tag_and_";    // tag_and
	private $registPre = "";            // registration_or_, 不过这个默认不需要前辍，除非程序指定注册ID
	
	private $readTimeout   = 30;
	private $pushUrl       = "https://api.jpush.cn/v3/push";
	private $userAgent      = "JPush-API-PHP-Client";
	private $liveLogTimeMin = 3;
	
	private $lastResponse = null; // 存储最后一次推送的响应状态
	
	private $_body = array(
			'platform' => 'all',
			'audience' => 'all',
			'notification' => array(),
	);
	
	private function _initPlatForm($data) {
		$platform = empty($data['extra']['platform']) ? 'all' : $data['extra']['platform'];
		if ($platform != "all") {
			$delimiter  = ',';
			$supportive = array('android', 'ios', 'winphone');
			
			if (strpos($platform, $delimiter) !== false) {
				$this->_body['platform'] = explode($delimiter, $platform);
			}
			
			elseif (in_array($platform, $supportive)) {
				$this->_body['platform'] = array($platform);
			}
		}
	}
	
	private function _initAudience($data)
	{
		$audience = array();
		if (is_array($data['sid'])) {
			$prefixMapper = self::_mapCallback($this->tagPre);
			$data['tag_sid'] = array_map($prefixMapper, $data['sid']);
			$audience['tag'] = $data['tag_sid'];
			unset($prefixMapper);
		} elseif (intval($data['sid']) > 0) {
			$audience['tag'] = array($this->tagPre . $data['sid']);
		}
		
		if (is_array($data['fid'])) {
			$prefixMapper = self::_mapCallback($this->tagAndPre);
			$data['tag_and_fid'] = array_map($prefixMapper, $data['fid']);
			$audience['tag_and'] = $data['tag_and_fid'];
			unset($prefixMapper);
		} elseif (!empty($data['fid'])) {
			$audience['tag_and'] = array($this->tagAndPre . $data['fid']);
		}
		
		if (is_array($data['rid'])) {
			$prefixMapper = self::_mapCallback($this->registPre);
			$data['regist_rid'] = array_map($prefixMapper, $data['rid']);
			$audience['registration_id'] = $data['regist_rid'];
			unset($prefixMapper);
		} elseif (!empty($data['rid'])) {
			$audience['registration_id'] = array($this->registPre . $data['rid']);
		}
		
		if (is_array($data['uid'])) {
			$prefixMapper = self::_mapCallback($this->aliasPre);
			$data['alias_uid'] = array_map($prefixMapper, $data['uid']);
			$audience['alias'] = $data['alias_uid'];
			unset($prefixMapper);
		} elseif (intval($data['uid']) > 0) {
			$audience['alias'] = array($this->aliasPre . $data['uid']);
		}
		
		unset($data);
		
		if (!empty($audience)) {
			$this->_body['audience'] = $audience;
		}
	}
	
	private function _initNotification($data)
	{
		$extras = array(
				'oper' => $data['oper'],
				'value' => $data['value'],
				'other' => $data['other'],
		);
		
		$alert = $data['msg'];
		
		$msg_ios = array(
				'alert' => $alert,
				'extras' => $extras,
		);
		$msg_and = array(
				'alert' => $alert,
				'title' => $this->msgTitle,
				'extras' => $extras,
		);
		
		$this->_body['notification'] = array('ios'=>$msg_ios, 'android'=>$msg_and);
	}
	
	private function _initHeader()
	{
		return array(
				'User-Agent' => $this->userAgent,
				'Connection' => 'Keep-Alive',
				'Charset' => 'UTF-8',
				'Content-Type' => 'application/json'
		);
	}
	
	/**
	 * 获取一个回调的闭包, 该闭包的功能是给一个字符串加前辍或后辍
	 *
	 * @param string $prefix
	 * @param string $suffix
	 *
	 * @return function($item0) -> string
	 */
	private static function _mapCallback($prefix = '', $suffix = '')
	{
		return function ($item0) use ($prefix, $suffix)
		{
			return $prefix . $item0 . $suffix;
		};
	}
	
	private function _request() {
		$options = array(
				'auth' => array($this->appkey, $this->msaterSecret),
				'timeout' => $this->readTimeout,
		);
		$request = null;
		
		try {
			$request = Requests::post($this->pushUrl, $this->_initHeader(), json_encode($this->_body), $options);
		} catch (\Exception $e) {
			var_dump($e);
			return null;
		}
		
		$response = $request->body;
		
		//print_r(json_decode($response, true)); exit(__FILE__.":".__LINE__);
		return $response;
	}
	
	// MARK DONE pushProvider.configKey: public or __set
	public function __set($var, $val)
	{
		$this->$var = $val;
	}
// 	public function __get($var)
// 	{
// 		return $this->$var;
// 	}
	
	public function __construct($config = array())
	{
	
	}
	
	/**
	 * 给定数据执行推送
	 *
	 * @param array $data
	 *
	 * @return void
	 */
	public function pushPerform($data)
	{
		if(self::DEBUG_MODE) {
			return ;
		}
		$this->_initPlatForm($data);
		$this->_initAudience($data);
		$this->_initNotification($data);
		$this->lastResponse = $this->_request();
	}
	
	/**
	 * 获取上一次推送的状态
	 *
	 * @return boolean
	 */
	public function getStatus()
	{
		if(self::DEBUG_MODE) {
			return true;
		}
		if(!isset($this->lastResponse)) {
			trigger_error(sprintf("%s::%s: You Shouldn't call me here, because no response now!", __CLASS__, __METHOD__), E_USER_ERROR);
			return false;
		}
		
		$responseArray = json_decode($this->lastResponse, true);
		//print_r($responseArray);
		/*
		Array
		(
				[msg_id] => 3528650090
				[error] => Array
				(
						[message] => cannot find user by this audience
						[code] => 1011
				)
		
		)
		*/
		$pushStatus = empty($responseArray['error']['code']);
		
		return $pushStatus;
	}
	
	public function getMessage()
	{
		if(self::DEBUG_MODE) {
			return 'DEBUG_MODE: OK!';
		}
		if(!isset($this->lastResponse)) {
			trigger_error(sprintf("%s::%s: You Shouldn't call me here, because no response now!", __CLASS__, __METHOD__), E_USER_ERROR);
			return false;
		}
		
		$responseArray = json_decode($this->lastResponse, true);
		$pushMessage = $responseArray['error']['message'];
		
		return $pushMessage;
	}
	
}